//SPDX-FileCopyrightText: Copyright 2022-2024 深圳市同心圆网络有限公司
//SPDX-License-Identifier: GPL-3.0-only

package project_testcase_api_serv

import (
	"context"
	"time"

	"atomgit.com/openlinksaas/api-server/api_common"
	"atomgit.com/openlinksaas/api-server/dao"
	"atomgit.com/openlinksaas/api-server/dao/testcase_dao"
	"atomgit.com/openlinksaas/api-server/dao/user_dao"
	"atomgit.com/openlinksaas/api-server/utils"
	"atomgit.com/openlinksaas/proto-gen-go.git/notices/notices_testcase"
	"atomgit.com/openlinksaas/proto-gen-go.git/project_testcase_api"
	"github.com/google/uuid"
	"go.mongodb.org/mongo-driver/mongo"
)

func (apiImpl *ProjectTestCaseApiImpl) CreateFolder(ctx context.Context, req *project_testcase_api.CreateFolderRequest) (*project_testcase_api.CreateFolderResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_testcase_api.CreateFolderResponse{
			Code:   project_testcase_api.CreateFolderResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	projectItem, _, _, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_testcase_api.CreateFolderResponse{
			Code:   project_testcase_api.CreateFolderResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_testcase_api.CreateFolderResponse{
			Code:   project_testcase_api.CreateFolderResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	} else if err != nil {
		return nil, err
	}
	if projectItem.Closed {
		return &project_testcase_api.CreateFolderResponse{
			Code:   project_testcase_api.CreateFolderResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	//检查父目录是否存在
	if req.ParentFolderId != "" {
		exist, err := testcase_dao.FolderInfoDao.Exist(ctx, req.ParentFolderId, req.ProjectId)
		if err != nil {
			return nil, err
		}
		if !exist {
			return &project_testcase_api.CreateFolderResponse{
				Code:   project_testcase_api.CreateFolderResponse_CODE_NO_PARENT_FOLDER,
				ErrMsg: "父目录不存在",
			}, nil
		}
	}

	folderId := uuid.NewString()
	timeNow := time.Now().UnixNano() / 1e6

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = testcase_dao.FolderInfoDao.Insert(sessCtx, &testcase_dao.FolderInfoDbItem{
			FolderId:       folderId,
			ProjectId:      req.ProjectId,
			Title:          req.Title,
			ParentFolderId: req.ParentFolderId,
			PermSetting: testcase_dao.PermSettingDbItem{
				UpdateForAll:          req.PermSetting.UpdateForAll,
				ExtraUpdateUserIdList: req.PermSetting.ExtraUpdateUserIdList,
			},
			SubFolderCount: 0,
			SubCaseCount:   0,
			CreateUserId:   sessionItem.UserId,
			CreateTime:     timeNow,
			UpdateUserId:   sessionItem.UserId,
			UpdateTime:     timeNow,
		})
		if err != nil {
			return nil, err
		}
		if req.ParentFolderId != "" {
			count, err := testcase_dao.FolderInfoDao.CountSubFolder(sessCtx, req.ParentFolderId, req.ProjectId)
			if err != nil {
				return nil, err
			}
			err = testcase_dao.FolderInfoDao.UpdateSubFolderCount(sessCtx, req.ParentFolderId, req.ProjectId, count)
			if err != nil {
				return nil, err
			}
		}
		return &project_testcase_api.CreateFolderResponse{
			Code:     project_testcase_api.CreateFolderResponse_CODE_OK,
			FolderId: folderId,
		}, nil
	})

	if err != nil {
		return nil, err
	}
	//发送通知
	go api_common.SendNoticeToProjectScope(context.Background(), req.ProjectId, &notices_testcase.NewFolderNotice{
		ProjectId:    req.ProjectId,
		FolderId:     folderId,
		CreateUserId: sessionItem.UserId,
	})
	return ret.(*project_testcase_api.CreateFolderResponse), nil
}

func (apiImpl *ProjectTestCaseApiImpl) UpdateFolder(ctx context.Context, req *project_testcase_api.UpdateFolderRequest) (*project_testcase_api.UpdateFolderResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_testcase_api.UpdateFolderResponse{
			Code:   project_testcase_api.UpdateFolderResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_testcase_api.UpdateFolderResponse{
			Code:   project_testcase_api.UpdateFolderResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_testcase_api.UpdateFolderResponse{
			Code:   project_testcase_api.UpdateFolderResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	} else if err != nil {
		return nil, err
	}
	if projectItem.Closed {
		return &project_testcase_api.UpdateFolderResponse{
			Code:   project_testcase_api.UpdateFolderResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	folderItem, err := testcase_dao.FolderInfoDao.Get(ctx, req.FolderId, req.ProjectId)
	if err != nil {
		return &project_testcase_api.UpdateFolderResponse{
			Code:   project_testcase_api.UpdateFolderResponse_CODE_NO_FOLDER,
			ErrMsg: "目录不存在",
		}, nil
	}

	//检查权限
	userPerm := apiImpl.calcFolderPerm(sessionItem, projectItem, roleItem, folderItem)
	if !userPerm.CanUpdate {
		return &project_testcase_api.UpdateFolderResponse{
			Code:   project_testcase_api.UpdateFolderResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	timeNow := time.Now().UnixNano() / 1e6

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = testcase_dao.FolderInfoDao.UpdateTitle(sessCtx, req.FolderId, req.ProjectId, req.Title, sessionItem.UserId, timeNow)
		if err != nil {
			return nil, err
		}
		return &project_testcase_api.UpdateFolderResponse{
			Code: project_testcase_api.UpdateFolderResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//发送通知
	go api_common.SendNoticeToProjectScope(context.Background(), req.ProjectId, &notices_testcase.UpdateFolderNotice{
		ProjectId: req.ProjectId,
		FolderId:  req.FolderId,
	})
	return ret.(*project_testcase_api.UpdateFolderResponse), nil
}

func (apiImpl *ProjectTestCaseApiImpl) SetFolderParent(ctx context.Context, req *project_testcase_api.SetFolderParentRequest) (*project_testcase_api.SetFolderParentResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_testcase_api.SetFolderParentResponse{
			Code:   project_testcase_api.SetFolderParentResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_testcase_api.SetFolderParentResponse{
			Code:   project_testcase_api.SetFolderParentResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_testcase_api.SetFolderParentResponse{
			Code:   project_testcase_api.SetFolderParentResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	} else if err != nil {
		return nil, err
	}
	if projectItem.Closed {
		return &project_testcase_api.SetFolderParentResponse{
			Code:   project_testcase_api.SetFolderParentResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	//列出所有目录信息
	allFolderItemList, err := testcase_dao.FolderInfoDao.ListByProject(ctx, req.ProjectId)
	if err != nil {
		return nil, err
	}
	allFolderItemMap := map[string]*testcase_dao.FolderInfoDbItem{}
	for _, allFolderItem := range allFolderItemList {
		allFolderItemMap[allFolderItem.FolderId] = allFolderItem
	}

	//检查目录权限
	folderItem, ok := allFolderItemMap[req.FolderId]
	if !ok {
		return &project_testcase_api.SetFolderParentResponse{
			Code:   project_testcase_api.SetFolderParentResponse_CODE_NO_FOLDER,
			ErrMsg: "目录不存在",
		}, nil
	}
	userPerm := apiImpl.calcFolderPerm(sessionItem, projectItem, roleItem, folderItem)
	if !userPerm.CanUpdate {
		return &project_testcase_api.SetFolderParentResponse{
			Code:   project_testcase_api.SetFolderParentResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	if folderItem.ParentFolderId == req.ParentFolderId {
		return &project_testcase_api.SetFolderParentResponse{
			Code: project_testcase_api.SetFolderParentResponse_CODE_OK,
		}, nil
	}

	//检查父目录
	if req.ParentFolderId != "" {
		_, ok = allFolderItemMap[req.ParentFolderId]
		if !ok {
			return &project_testcase_api.SetFolderParentResponse{
				Code:   project_testcase_api.SetFolderParentResponse_CODE_NO_PARENT_FOLDER,
				ErrMsg: "父目录不存在",
			}, nil
		}
	}

	//检查路径循环
	tmpFolderId := req.ParentFolderId
	for i := 0; i < 99; i++ {
		if tmpFolderId == "" {
			break
		}
		if tmpFolderId == req.FolderId {
			return &project_testcase_api.SetFolderParentResponse{
				Code:   project_testcase_api.SetFolderParentResponse_CODE_CIRCLE_LOOP,
				ErrMsg: "不能移动到子目录",
			}, nil
		}
		tmpFolder, ok := allFolderItemMap[tmpFolderId]
		if !ok {
			return &project_testcase_api.SetFolderParentResponse{
				Code:   project_testcase_api.SetFolderParentResponse_CODE_NO_PARENT_FOLDER,
				ErrMsg: "父目录不存在",
			}, nil
		}
		tmpFolderId = tmpFolder.ParentFolderId
	}

	timeNow := time.Now().UnixNano() / 1e6

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = testcase_dao.FolderInfoDao.UpdateParentFolder(sessCtx, req.FolderId, req.ProjectId, req.ParentFolderId, sessionItem.UserId, timeNow)
		if err != nil {
			return nil, err
		}
		if folderItem.ParentFolderId != "" {
			count, err := testcase_dao.FolderInfoDao.CountSubFolder(sessCtx, folderItem.ParentFolderId, req.ProjectId)
			if err != nil {
				return nil, err
			}
			err = testcase_dao.FolderInfoDao.UpdateSubFolderCount(sessCtx, folderItem.ParentFolderId, req.ProjectId, count)
			if err != nil {
				return nil, err
			}
		}
		if req.ParentFolderId != "" {
			count, err := testcase_dao.FolderInfoDao.CountSubFolder(sessCtx, req.ParentFolderId, req.ProjectId)
			if err != nil {
				return nil, err
			}
			err = testcase_dao.FolderInfoDao.UpdateSubFolderCount(sessCtx, req.ParentFolderId, req.ProjectId, count)
			if err != nil {
				return nil, err
			}
		}
		return &project_testcase_api.SetFolderParentResponse{
			Code: project_testcase_api.SetFolderParentResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//发送通知
	go api_common.SendNoticeToProjectScope(context.Background(), req.ProjectId, &notices_testcase.UpdateFolderNotice{
		ProjectId: req.ProjectId,
		FolderId:  req.FolderId,
	})
	return ret.(*project_testcase_api.SetFolderParentResponse), nil
}

func (apiImpl *ProjectTestCaseApiImpl) ListFolder(ctx context.Context, req *project_testcase_api.ListFolderRequest) (*project_testcase_api.ListFolderResponse, error) {
	emptyList := []*project_testcase_api.FolderInfo{}

	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_testcase_api.ListFolderResponse{
			Code:       project_testcase_api.ListFolderResponse_CODE_WRONG_SESSION,
			ErrMsg:     "会话不存在",
			FolderList: emptyList,
		}, nil
	}
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_testcase_api.ListFolderResponse{
			Code:       project_testcase_api.ListFolderResponse_CODE_NO_PROJECT,
			ErrMsg:     "项目不存在",
			FolderList: emptyList,
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_testcase_api.ListFolderResponse{
			Code:       project_testcase_api.ListFolderResponse_CODE_NO_PERMISSION,
			ErrMsg:     "没有权限",
			FolderList: emptyList,
		}, nil
	} else if err != nil {
		return nil, err
	}

	//检查目录是否存在
	if req.ParentFolderId != "" {
		exist, err := testcase_dao.FolderInfoDao.Exist(ctx, req.ParentFolderId, req.ProjectId)
		if err != nil {
			return nil, err
		}
		if !exist {
			return &project_testcase_api.ListFolderResponse{
				Code:       project_testcase_api.ListFolderResponse_CODE_NO_PARENT_FOLDER,
				ErrMsg:     "父目录不存在",
				FolderList: emptyList,
			}, nil
		}
	}

	folderItemList, err := testcase_dao.FolderInfoDao.ListSubFolder(ctx, req.ParentFolderId, req.ProjectId)
	if err != nil {
		return nil, err
	}
	//获取用户信息
	userIdList := []string{}
	for _, folderItem := range folderItemList {
		userIdList = append(userIdList, folderItem.CreateUserId)
		if folderItem.CreateUserId != folderItem.UpdateUserId {
			userIdList = append(userIdList, folderItem.UpdateUserId)
		}
	}
	userItemList, err := user_dao.UserInfoDao.ListById(ctx, userIdList)
	if err != nil {
		return nil, err
	}
	userItemMap := map[string]*user_dao.UserInfoDbItem{}
	for _, userItem := range userItemList {
		userItemMap[userItem.UserId] = userItem
	}

	//生成结果
	folderInfoList := []*project_testcase_api.FolderInfo{}
	for _, folderItem := range folderItemList {
		folderInfo := folderItem.ToFolderInfo()
		createUser, ok := userItemMap[folderItem.CreateUserId]
		if ok {
			folderInfo.CreateDisplayName = createUser.BasicInfo.DisplayName
			folderInfo.CreateLogoUri = createUser.BasicInfo.LogoUri
		}
		updateUser, ok := userItemMap[folderItem.UpdateUserId]
		if ok {
			folderInfo.UpdateDisplayName = updateUser.BasicInfo.DisplayName
			folderInfo.UpdateLogoUri = updateUser.BasicInfo.LogoUri
		}
		folderInfo.UserPerm = apiImpl.calcFolderPerm(sessionItem, projectItem, roleItem, folderItem)
		folderInfoList = append(folderInfoList, folderInfo)
	}

	return &project_testcase_api.ListFolderResponse{
		Code:       project_testcase_api.ListFolderResponse_CODE_OK,
		FolderList: folderInfoList,
	}, nil
}

func (apiImpl *ProjectTestCaseApiImpl) GetFolder(ctx context.Context, req *project_testcase_api.GetFolderRequest) (*project_testcase_api.GetFolderResponse, error) {
	emptyInfo := &project_testcase_api.FolderInfo{
		PermSetting: &project_testcase_api.PermSetting{
			ExtraUpdateUserIdList: []string{},
		},
		UserPerm: &project_testcase_api.UserPerm{},
	}

	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_testcase_api.GetFolderResponse{
			Code:       project_testcase_api.GetFolderResponse_CODE_WRONG_SESSION,
			ErrMsg:     "会话不存在",
			FolderInfo: emptyInfo,
		}, nil
	}
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_testcase_api.GetFolderResponse{
			Code:       project_testcase_api.GetFolderResponse_CODE_NO_PROJECT,
			ErrMsg:     "项目不存在",
			FolderInfo: emptyInfo,
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_testcase_api.GetFolderResponse{
			Code:       project_testcase_api.GetFolderResponse_CODE_NO_PERMISSION,
			ErrMsg:     "没有权限",
			FolderInfo: emptyInfo,
		}, nil
	} else if err != nil {
		return nil, err
	}

	folderItem, err := testcase_dao.FolderInfoDao.Get(ctx, req.FolderId, req.ProjectId)
	if err != nil {
		return &project_testcase_api.GetFolderResponse{
			Code:       project_testcase_api.GetFolderResponse_CODE_NO_FOLDER,
			ErrMsg:     "目录不存在",
			FolderInfo: emptyInfo,
		}, nil
	}

	//获取用户信息
	userItemList, err := user_dao.UserInfoDao.ListById(ctx, []string{folderItem.CreateUserId, folderItem.UpdateUserId})
	if err != nil {
		return nil, err
	}
	userItemMap := map[string]*user_dao.UserInfoDbItem{}
	for _, userItem := range userItemList {
		userItemMap[userItem.UserId] = userItem
	}

	//生成结果
	folderInfo := folderItem.ToFolderInfo()
	createUser, ok := userItemMap[folderItem.CreateUserId]
	if ok {
		folderInfo.CreateDisplayName = createUser.BasicInfo.DisplayName
		folderInfo.CreateLogoUri = createUser.BasicInfo.LogoUri
	}
	updateUser, ok := userItemMap[folderItem.UpdateUserId]
	if ok {
		folderInfo.UpdateDisplayName = updateUser.BasicInfo.DisplayName
		folderInfo.UpdateLogoUri = updateUser.BasicInfo.LogoUri
	}
	folderInfo.UserPerm = apiImpl.calcFolderPerm(sessionItem, projectItem, roleItem, folderItem)

	return &project_testcase_api.GetFolderResponse{
		Code:       project_testcase_api.GetFolderResponse_CODE_OK,
		FolderInfo: folderInfo,
	}, nil
}

func (apiImpl *ProjectTestCaseApiImpl) RemoveFolder(ctx context.Context, req *project_testcase_api.RemoveFolderRequest) (*project_testcase_api.RemoveFolderResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_testcase_api.RemoveFolderResponse{
			Code:   project_testcase_api.RemoveFolderResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_testcase_api.RemoveFolderResponse{
			Code:   project_testcase_api.RemoveFolderResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_testcase_api.RemoveFolderResponse{
			Code:   project_testcase_api.RemoveFolderResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	} else if err != nil {
		return nil, err
	}
	if projectItem.Closed {
		return &project_testcase_api.RemoveFolderResponse{
			Code:   project_testcase_api.RemoveFolderResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	folderItem, err := testcase_dao.FolderInfoDao.Get(ctx, req.FolderId, req.ProjectId)
	if err != nil {
		return &project_testcase_api.RemoveFolderResponse{
			Code: project_testcase_api.RemoveFolderResponse_CODE_OK,
		}, nil
	}

	//检查权限
	userPerm := apiImpl.calcFolderPerm(sessionItem, projectItem, roleItem, folderItem)
	if !userPerm.CanRemove {
		return &project_testcase_api.RemoveFolderResponse{
			Code:   project_testcase_api.RemoveFolderResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = testcase_dao.FolderInfoDao.Remove(sessCtx, req.FolderId, req.ProjectId)
		if err != nil {
			return nil, err
		}
		if folderItem.ParentFolderId != "" {
			count, err := testcase_dao.FolderInfoDao.CountSubFolder(sessCtx, folderItem.ParentFolderId, req.ProjectId)
			if err != nil {
				return nil, err
			}
			err = testcase_dao.FolderInfoDao.UpdateSubFolderCount(sessCtx, folderItem.ParentFolderId, req.ProjectId, count)
			if err != nil {
				return nil, err
			}
		}
		return &project_testcase_api.RemoveFolderResponse{
			Code: project_testcase_api.RemoveFolderResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//发送通知
	go api_common.SendNoticeToProjectScope(context.Background(), req.ProjectId, &notices_testcase.RemoveFolderNotice{
		ProjectId: req.ProjectId,
		FolderId:  req.FolderId,
	})
	return ret.(*project_testcase_api.RemoveFolderResponse), nil
}

func (apiImpl *ProjectTestCaseApiImpl) UpdateFolderPerm(ctx context.Context, req *project_testcase_api.UpdateFolderPermRequest) (*project_testcase_api.UpdateFolderPermResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_testcase_api.UpdateFolderPermResponse{
			Code:   project_testcase_api.UpdateFolderPermResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_testcase_api.UpdateFolderPermResponse{
			Code:   project_testcase_api.UpdateFolderPermResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_testcase_api.UpdateFolderPermResponse{
			Code:   project_testcase_api.UpdateFolderPermResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	} else if err != nil {
		return nil, err
	}
	if projectItem.Closed {
		return &project_testcase_api.UpdateFolderPermResponse{
			Code:   project_testcase_api.UpdateFolderPermResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	folderItem, err := testcase_dao.FolderInfoDao.Get(ctx, req.FolderId, req.ProjectId)
	if err != nil {
		return &project_testcase_api.UpdateFolderPermResponse{
			Code:   project_testcase_api.UpdateFolderPermResponse_CODE_NO_FOLDER,
			ErrMsg: "目录不存在",
		}, nil
	}

	//检查权限
	userPerm := apiImpl.calcFolderPerm(sessionItem, projectItem, roleItem, folderItem)
	if !userPerm.CanUpdate {
		return &project_testcase_api.UpdateFolderPermResponse{
			Code:   project_testcase_api.UpdateFolderPermResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	timeNow := time.Now().UnixNano() / 1e6

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = testcase_dao.FolderInfoDao.UpdatePermSetting(sessCtx, req.FolderId, req.ProjectId, &testcase_dao.PermSettingDbItem{
			UpdateForAll:          req.PermSetting.UpdateForAll,
			ExtraUpdateUserIdList: req.PermSetting.ExtraUpdateUserIdList,
		}, sessionItem.UserId, timeNow)
		if err != nil {
			return nil, err
		}
		return &project_testcase_api.UpdateFolderPermResponse{
			Code: project_testcase_api.UpdateFolderPermResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//发送通知
	go api_common.SendNoticeToProjectScope(context.Background(), req.ProjectId, &notices_testcase.UpdateFolderNotice{
		ProjectId: req.ProjectId,
		FolderId:  req.FolderId,
	})
	return ret.(*project_testcase_api.UpdateFolderPermResponse), nil
}

func (apiImpl *ProjectTestCaseApiImpl) GetFolderPath(ctx context.Context, req *project_testcase_api.GetFolderPathRequest) (*project_testcase_api.GetFolderPathResponse, error) {
	emptyList := []*project_testcase_api.FolderPathItem{}

	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_testcase_api.GetFolderPathResponse{
			Code:     project_testcase_api.GetFolderPathResponse_CODE_WRONG_SESSION,
			ErrMsg:   "会话不存在",
			PathList: emptyList,
		}, nil
	}
	_, _, _, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_testcase_api.GetFolderPathResponse{
			Code:     project_testcase_api.GetFolderPathResponse_CODE_NO_PROJECT,
			ErrMsg:   "项目不存在",
			PathList: emptyList,
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_testcase_api.GetFolderPathResponse{
			Code:     project_testcase_api.GetFolderPathResponse_CODE_NO_PERMISSION,
			ErrMsg:   "没有权限",
			PathList: emptyList,
		}, nil
	} else if err != nil {
		return nil, err
	}

	//列出所有目录信息
	allFolderItemList, err := testcase_dao.FolderInfoDao.ListByProject(ctx, req.ProjectId)
	if err != nil {
		return nil, err
	}
	allFolderItemMap := map[string]*testcase_dao.FolderInfoDbItem{}
	for _, allFolderItem := range allFolderItemList {
		allFolderItemMap[allFolderItem.FolderId] = allFolderItem
	}

	//生成结果
	tmpFolderId := req.FolderId
	pathList := []*project_testcase_api.FolderPathItem{}
	for i := 0; i < 99; i++ { //防止死循环
		if tmpFolderId == "" {
			break
		}
		folderItem, ok := allFolderItemMap[tmpFolderId]
		if !ok {
			return &project_testcase_api.GetFolderPathResponse{
				Code:     project_testcase_api.GetFolderPathResponse_CODE_NO_FOLDER,
				ErrMsg:   "目录不存在",
				PathList: emptyList,
			}, nil
		}
		pathList = append(pathList, &project_testcase_api.FolderPathItem{
			FolderId: folderItem.FolderId,
			Title:    folderItem.Title,
		})
		tmpFolderId = folderItem.ParentFolderId
	}
	//倒序
	retList := make([]*project_testcase_api.FolderPathItem, len(pathList))
	for index, path := range pathList {
		retList[len(pathList)-index-1] = path
	}

	return &project_testcase_api.GetFolderPathResponse{
		Code:     project_testcase_api.GetFolderPathResponse_CODE_OK,
		PathList: retList,
	}, nil
}

func (apiImpl *ProjectTestCaseApiImpl) ListAllFolder(ctx context.Context, req *project_testcase_api.ListAllFolderRequest) (*project_testcase_api.ListAllFolderResponse, error) {
	emptyList := []*project_testcase_api.SimpleFolderInfo{}

	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_testcase_api.ListAllFolderResponse{
			Code:       project_testcase_api.ListAllFolderResponse_CODE_WRONG_SESSION,
			ErrMsg:     "会话不存在",
			FolderList: emptyList,
		}, nil
	}
	_, _, _, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_testcase_api.ListAllFolderResponse{
			Code:       project_testcase_api.ListAllFolderResponse_CODE_NO_PROJECT,
			ErrMsg:     "项目不存在",
			FolderList: emptyList,
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_testcase_api.ListAllFolderResponse{
			Code:       project_testcase_api.ListAllFolderResponse_CODE_NO_PERMISSION,
			ErrMsg:     "没有权限",
			FolderList: emptyList,
		}, nil
	} else if err != nil {
		return nil, err
	}

	folderItemList, err := testcase_dao.FolderInfoDao.ListByProject(ctx, req.ProjectId)
	if err != nil {
		return nil, err
	}
	folderList := []*project_testcase_api.SimpleFolderInfo{}
	for _, folderItem := range folderItemList {
		folderList = append(folderList, &project_testcase_api.SimpleFolderInfo{
			FolderId:       folderItem.FolderId,
			Title:          folderItem.Title,
			ParentFolderId: folderItem.ParentFolderId,
		})
	}

	return &project_testcase_api.ListAllFolderResponse{
		Code:       project_testcase_api.ListAllFolderResponse_CODE_OK,
		FolderList: folderList,
	}, nil
}
